home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / language / sozobon2.zoo / hcc / g2.c < prev    next >
C/C++ Source or Header  |  1990-12-16  |  13KB  |  655 lines

  1. /* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
  2.  * Patched -- PvO -- see file patch *
  3.  *
  4.  * Permission is granted to anyone to use this software for any purpose
  5.  * on any computer system, and to redistribute it freely, with the
  6.  * following restrictions:
  7.  * 1) No charge may be made other than reasonable charges for reproduction.
  8.  * 2) Modified versions must be clearly marked as such.
  9.  * 3) The authors are not responsible for any harmful consequences
  10.  *    of using this software, even if they result from defects in it.
  11.  *
  12.  *    g2.c
  13.  *
  14.  *    Generate code for binary nodes.
  15.  */
  16.  
  17. #include <stdio.h>
  18. #include "param.h"
  19. #include "nodes.h"
  20. #include "flags.h"
  21. #include "bstok.h"
  22. #include "gen.h"
  23. #include "ops.h"
  24.  
  25. #define FAIL    0
  26. #define OKAY    1
  27.  
  28. extern int cookflags[];
  29.  
  30. #define isimmed(np)    ((np)->g_flags & IMMEDID)
  31. #define isareg(np)    ((np)->g_token == REGVAR && (np)->g_rno >= AREG)
  32. /* Patched -- PvO */
  33. #define isdreg(np)    ((np)->g_token == REGVAR && (np)->g_rno < AREG)
  34.  
  35. struct bop {
  36.     char *s_op, *u_op;
  37.     int opflags;
  38. } bops[] = {
  39.     {"muls",    "mulu",    EOPD |ASSOC},
  40.     {"divs",    "divu",    EOPD},
  41.     {"divs",    "divu", EOPD},
  42.     {"and",        "and",    EOPD|DOPE|IOPE |ASSOC},
  43.     {"or",        "or",    EOPD|DOPE|IOPE |ASSOC},
  44.     {"eor",        "eor",    DOPE|IOPE |ASSOC},
  45.     {"add",        "add",    EOPD|DOPE|EOPA|IOPE|AOPA|AOPD |ASSOC},
  46.     {"sub",        "sub",    EOPD|DOPE|EOPA|IOPE|AOPA|AOPD},
  47.     {"asl",        "lsl",    DOPD|QOPD|ONEOPM},
  48.     {"asr",        "lsr",    DOPD|QOPD|ONEOPM},
  49. };
  50.  
  51. char *tstnm[] = {
  52.     "lt",        /* < */
  53.     "gt",        /* > */
  54.     "le",        /* <= */
  55.     "ge",        /* >= */
  56.     "eq",        /* == */
  57.     "ne",        /* != */
  58. };
  59.  
  60. int tstx[] = {
  61.     B_LT, B_GT, B_LE, B_GE, B_EQ, B_NE
  62. };
  63.  
  64. char *utstnm[] = {
  65.     "cs",        /* < */
  66.     "hi",        /* > */
  67.     "ls",        /* <= */
  68.     "cc",        /* >= */
  69.     "eq",        /* == */
  70.     "ne",        /* != */
  71. };
  72.  
  73. int utstx[] = {
  74.     B_ULT, B_UGT, B_ULE, B_UGE, B_EQ, B_NE
  75. };
  76.  
  77. b_eval(np, cookie)
  78. register NODEP np;
  79. {
  80.     NODEP lp = np->n_left, rp = np->n_right;
  81.     NODEP tp;
  82.     int lcook = FORADR, rcook = FORADR;
  83.  
  84.     switch (np->g_token) {        /* special cookies */
  85.     case DOUBLE '&':
  86.     case DOUBLE '|':
  87.         lcook = rcook = FORCC;
  88.         break;
  89.     case '?':
  90.         lcook = FORCC;
  91.         break;
  92.     case '(':
  93.         rcook = FORPUSH;
  94.         break;
  95.     case ',':
  96.         if (np->g_offs)    /* function args */
  97.             lcook = rcook = FORPUSH;
  98.         else {
  99.             lcook = FORSIDE;
  100.             rcook = cookie;
  101.         }
  102.         break;
  103.     case '=':
  104.         rcook = FORIMA;
  105.         break;
  106.     case '+':
  107.     case '-':
  108.         tp = rp;
  109.         while (tp->g_token == TCONV && tp->g_ty != ET_F)
  110.             tp = tp->n_left;
  111.         if (tp->g_token == ICON)
  112.             lcook = FORIMA;
  113.         break;        
  114.     }
  115.  
  116.     if (np->g_type == EV_LR) {
  117.         if (eval(lp,lcook) == FAIL)
  118.             return FAIL;
  119.         freetmps(lp);
  120.         if (eval(rp,rcook) == FAIL)
  121.             return FAIL;
  122.         freetmps(rp);
  123.     } else if (np->g_type == EV_RL) {
  124.         if (eval(rp,rcook) == FAIL)
  125.             return FAIL;
  126.         freetmps(rp);
  127.         if (eval(lp,lcook) == FAIL)
  128.             return FAIL;
  129.         freetmps(lp);
  130.     } else {    /* EV_LRSEP */
  131.         if (eval(lp,lcook) == FAIL)
  132.             return FAIL;
  133.         freetmps(lp);
  134.         free1(NULL, lp);
  135.         if (eval(rp,rcook) == FAIL)
  136.             return FAIL;
  137.         freetmps(rp);
  138.     }
  139.     return b_sube(np, cookflags[cookie]);
  140. }
  141.  
  142. b_sube(np, flags)
  143. register NODEP np;
  144. {
  145.     NODEP lp = np->n_left, rp = np->n_right;
  146.     register int i, r;
  147.     int argsize;
  148.     char buf[40];
  149.     
  150.     if (isassign(np->g_token))
  151.         return as_eval(np);
  152.  
  153.     switch (np->g_token) {
  154.     case '=':
  155.         if (specasn(np, flags) || strasn(np))
  156.             return OKAY;
  157.         inherit(np);
  158.         addcode(np, "\tmove.S\t>A,<A\n");
  159.         return OKAY;
  160.  
  161.     case '(':
  162.         argsize = argmod(rp);
  163.         free1(NULL,rp);
  164.         if (np->g_ty == ET_A) {        /* struct returned */
  165.             frc_ral(AREG);
  166.             indir(np, AREG);
  167.         } else {
  168.             frc_ral(0);
  169.             retreg(np, 0);
  170.         }
  171.         sprintf(buf, "\tjsr\t<A\n\tadd.w\t#%d,sp\n", argsize);
  172.         addcode(np, buf);
  173.         return OKAY;
  174.  
  175.     case ',':
  176.         if (np->g_offs == 0)    /* normal ',' */
  177.             rinherit(np);
  178.         return OKAY;
  179.  
  180.     case DOUBLE '&':
  181.         free1(NULL, rp);
  182.         r = ralloc(0);
  183.         retreg(np, r);
  184.         holdlbls(np);
  185.         np->g_betw = iscc(lp) ? "<FL1\n" :
  186.             "<Q\tbeq\tL1\n";
  187.         addcode(np, iscc(rp) ? ">FL1\n" :
  188.             ">Q\tbeq\tL1\n");
  189.         addcode(np, "\tmoveq\t#1,A\n");
  190.         addcode(np, "\tbra\tL2\nL1:\tclr\tA\nL2:\n");
  191.         return OKAY;
  192.  
  193.     case DOUBLE '|':
  194.         free1(NULL, rp);
  195.         r = ralloc(0);
  196.         retreg(np, r);
  197.         holdlbls(np);
  198.         np->g_betw = iscc(lp) ? "<TL1\n" :
  199.             "<Q\tbne\tL1\n";
  200.         addcode(np, iscc(rp) ? ">TL1\n" :
  201.             ">Q\tbne\tL1\n");
  202.         addcode(np, "\tclr\tA\n");
  203.         addcode(np, "\tbra\tL2\nL1:\tmoveq\t#1,A\nL2:\n");
  204.         return OKAY;
  205.  
  206.     case '?':
  207.         rinherit(np);
  208.         rinhlbls(np);
  209.         np->g_betw = iscc(lp) ? "<FL1\n" : "<Q\tbeq\tL1\n";
  210.         return OKAY;
  211.  
  212.     case ':':
  213.         free1(NULL, rp);
  214.         r = ralloc(0);
  215.         retreg(np, r);
  216.         holdlbls(np);
  217.         np->g_betw = same_a(np, lp) ?
  218.             "\tbra\tL2\nL1:\n"  :
  219.             "\tmove.S\t<A,A\n\tbra\tL2\nL1:\n";
  220.         if (!same_a(np, rp))
  221.             addcode(np, "\tmove.S\t>A,A\n");
  222.         addcode(np, "L2:\n");
  223.         return OKAY;
  224.  
  225.     case '<':
  226.         i = 0;  goto dotst;
  227.     case '>':
  228.         i = 1;  goto dotst;
  229.     case LTEQ:
  230.         i = 2;  goto dotst;
  231.     case GTEQ:
  232.         i = 3;  goto dotst;
  233.     case DOUBLE '=':
  234.         i = 4;  goto dotst;
  235.     case NOTEQ:
  236.         i = 5;
  237. dotst:
  238.         fix_cmp(np, EOPD|EOPA|IOPE|AOPA|AOPD);
  239.         if (flags & CC_OK) {
  240.             np->g_token = (lp->g_ty == ET_U ?
  241.             utstx[i] : tstx[i]) + BR_TOK;
  242.         } else {
  243.             strcpy(np->n_name, lp->g_ty == ET_U ?
  244.             utstnm[i] : tstnm[i]);
  245.             r = ralloc(0);
  246.             retreg(np, r);
  247.             addcode(np, "\tsN\tA\n\tand.w\t#1,A\n");
  248.         }
  249.         return OKAY;
  250.  
  251.     case '*':
  252.         return fixmul(np, bops[0].opflags);
  253.     case '/':
  254.         return fixdiv(np, bops[1].opflags);
  255.     case '%':
  256.         return fixmod(np, bops[2].opflags);
  257.     case '&':    i = 3;  goto doop;
  258.     case '|':    i = 4;  goto doop;
  259.     case '^':    i = 5;    goto doop;
  260.     case '+':
  261.         if (optadd(np, flags, 1))
  262.             return OKAY;
  263.             i = 6;  goto doop;
  264.     case '-':
  265.         if (optadd(np, flags, -1))
  266.             return OKAY;
  267.             i = 7;  goto doop;
  268.     case DOUBLE '<':i = 8;  goto doop;
  269.     case DOUBLE '>':i = 9;
  270. doop:
  271.         strcpy(np->n_name, np->g_ty == ET_U ?
  272.             bops[i].u_op : bops[i].s_op);
  273.         r = fix2ops(np, bops[i].opflags);
  274.         cc_hack(np);
  275.         return r;
  276.     case FIELDAS:
  277.         return fldasn(np, flags);
  278.     default:
  279.         printf("Weird b_eval %s ", np->n_name);
  280.         return FAIL;
  281.     }
  282. }
  283.  
  284. as_eval(np)
  285. register NODEP np;
  286. {
  287.     NODEP rp = np->n_right;
  288.     register int op, i, r;
  289.  
  290.     rp = np->n_right;
  291.  
  292.     op = np->g_token;
  293.     op -= ASSIGN 0;
  294.     switch (op) {
  295.  
  296.     /* these get unfolded now */
  297.     case '*':
  298.             return fixamul(np, bops[0].opflags);
  299.     case '/':
  300.             return fixadiv(np, bops[1].opflags);
  301.     case '%':
  302.             return fixamod(np, bops[2].opflags);
  303.     case '&':    i = 3;  goto doop;
  304.     case '|':    i = 4;  goto doop;
  305.     case '^':    i = 5;    goto doop;
  306.     case '+':    i = 6;  goto doop;
  307.     case '-':    i = 7;  goto doop;
  308.     case DOUBLE '<':i = 8;  goto doop;
  309.     case DOUBLE '>':i = 9;
  310. doop:
  311.         strcpy(np->n_name, np->g_ty == ET_U ?
  312.             bops[i].u_op : bops[i].s_op);
  313.         r = fix_asn(np, bops[i].opflags);
  314.         cc_hack(np);
  315.         return r;
  316.  
  317.     default:
  318.         printf("Weird as_eval %s ", np->n_name);
  319.         return FAIL;
  320.     }
  321. }
  322.  
  323. rinherit(np)
  324. register NODEP np;
  325. {
  326.     register NODEP rp = np->n_right;
  327.  
  328.     np->g_token = rp->g_token;
  329.     np->g_offs = rp->g_offs;
  330.     np->g_rno = rp->g_rno;
  331.     np->g_flags |= RCHILDNM | (rp->g_flags & IMMEDID);
  332. }
  333.  
  334. argmod(np)
  335. register NODEP np;
  336. {
  337.     int size = 0;
  338.  
  339.     if (np->g_token == ',') {
  340.         np->g_type = EV_RL;
  341.         size += argmod(np->n_right);
  342.         size += argmod(np->n_left);
  343.         return size;
  344.     }
  345.     size += onearg(np);
  346.     return size;
  347. }
  348.  
  349. onearg(np)
  350. register NODEP np;
  351. {
  352.     int rv;
  353.  
  354.     /* hack small ICON */
  355.     if (np->g_sz == 1 && np->g_token == ICON)
  356.         np->g_sz = 2;
  357.     /* hack push of 0 */
  358.     if (np->g_token == ICON && np->g_offs == 0 && isimmed(np)) {
  359.         addcode(np, "\tclr.S\t-(sp)\n");
  360.         return (int)np->g_sz;
  361.     }
  362.     /* hack push of #OREG */
  363.     if (np->g_token == OREG && isimmed(np)) {
  364.         np->g_flags &= ~IMMEDID;
  365.         addcode(np, "\tpea\tA\n");
  366.         return 4;
  367.     }
  368.  
  369.     if (np->g_ty == ET_A) {
  370.         rv = strpush(np);
  371.         freetmps(np);
  372.         free1(NULL,np);
  373.         return rv;
  374.     }
  375.  
  376.     switch (np->g_sz) {
  377.     case 1:
  378. /* Patched -- PvO */
  379.         if (isdreg(np))
  380.         addcode(np, (np->g_ty == ET_U) ?
  381.            "\tand.w\t#255,A\n\tmove.w\tA,-(sp)\n" :
  382.            "\text.w\tA\n\tmove.w\tA,-(sp)\n" );
  383.         else
  384.         addcode(np, (np->g_ty == ET_U) ?